import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import os
import json
from CollectResultsGUI import CollectResults
import DashscopeAPI as ds


class ResultBase:
    def __init__(self, bag_path, parameters={}) -> None:
        self.bag_path = bag_path
        self.parameters = parameters
        self.default_result = "failure"
        if "collision" in self.parameters:
            print(self.parameters["collision"])
            if not self.parameters["collision"]:
                self.default_result = "success"
        if self.bag_path == "":
            default_bag_path = self.GetDefaultBagPath()
            default_bag_dir = os.path.dirname(default_bag_path)
            self.bag_path = filedialog.askopenfilename(
                filetypes=[("rosbag", "*.bag")],
                initialdir=default_bag_dir,
                initialfile=default_bag_path,
                title="Select a rosbag file",
            )
        self.SetupGUI()
        self.result_json_file = os.path.dirname(self.bag_path)
        self.base_name = os.path.basename(self.bag_path).split(".")[0]
        self.result_json_file = os.path.join(
            self.result_json_file, self.base_name + ".json"
        )
        self.results = []
        if os.path.exists(self.result_json_file):
            bag_path, self.results = self.ReadResultJSON(self.result_json_file)
            if len(self.results) > 0:
                self.select_result.config(
                    values=[f"RUN{i+1:03d}" for i in range(len(self.results))]
                )
                self.select_result.set(f"RUN{len(self.results):03d}")
                self.UpdateResults(self.results[-1])

    def SetupGUI(self):
        self.result_var = tk.StringVar(value=self.default_result)
        tk.Label(self, text="Choose Result:").grid(row=0, column=0)
        self.success_checkbox = tk.Checkbutton(
            self,
            text="Success",
            variable=self.result_var,
            onvalue="success",
            offvalue="",
        )
        self.success_checkbox.grid(row=0, column=1)
        self.failure_checkbox = tk.Checkbutton(
            self,
            text="Failure",
            variable=self.result_var,
            onvalue="failure",
            offvalue="",
        )
        self.failure_checkbox.grid(row=0, column=2)
        self.select_result = ttk.Combobox(
            self, textvariable=["No previous result"], state="readonly"
        )
        self.select_result.bind("<<ComboboxSelected>>", self.OnResSelected)
        self.select_result.grid(row=0, column=3)

        tk.Label(self, text="Comment:").grid(row=1, column=0)
        self.comment_text = tk.Text(self, height=5, width=50, font=("Ariel", 12))
        self.comment_text.insert(tk.END, "")
        self.comment_text.grid(row=2, column=0, columnspan=6)

        self.delet_button = ttk.Button(self, text="delete", command=self.DeleteBag)
        self.delet_button.grid(row=3, column=0)
        self.correct_button = ttk.Button(
            self, text="correct", command=self.CorrectSequence
        )
        self.correct_button.grid(row=3, column=1)
        if not ds.DASHSCOPE_IMPORT_SUCCESS:
            self.correct_button.config(state="disabled")
        confirm_button = ttk.Button(self, text="confirm", command=self.ConfirmSelection)
        confirm_button.grid(row=3, column=2)

        self.menu_bar = tk.Menu(self)
        self.export_menu = tk.Menu(self.menu_bar, tearoff=0)
        self.export_menu.add_command(label="Generate PDF", command=self.ExportResults)
        self.menu_bar.add_cascade(label="Export", menu=self.export_menu)

    def OnResSelected(self, event):
        selected = self.select_result.get()
        index = int(selected[3:])
        self.UpdateResults(self.results[index - 1])

    def GetDefaultBagPath(self):
        config_json_path = os.path.join(
            os.path.dirname(os.path.abspath(__file__)), "config", "default.json"
        )
        if not os.path.exists(config_json_path):
            return ""
        with open(config_json_path, "r") as file:
            data = json.load(file)
            bag_path = data.get("last_bag", "")
            return bag_path

    def ExportResults(self):
        bag_path = self.bag_path
        if not bag_path or not bag_path.endswith(".bag"):
            print("Please input the rosbag file path.")
            return
        result_win = CollectResults(self, bag_path)
        result_win.grab_set()

    def ConfirmSelection(self):
        if self.bag_path == "":
            self.destroy()
            return
        is_save = messagebox.askyesno("Save Result", "Do you want save this result?")
        if is_save:
            result_var = self.result_var.get()
            comment = self.comment_text.get("1.0", tk.END).strip()
            result = {
                "result": result_var,
                "comment": comment,
                "parameters": self.parameters,
            }
            self.results.append(result)
            data = {"bag": self.bag_path}
            for i, result in enumerate(self.results):
                data[f"RUN{i:03d}"] = result
            with open(self.result_json_file, "w") as file:
                json.dump(data, file, indent=4)
            messagebox.showinfo(
                "Save Result", f"Result has been save into {self.result_json_file}."
            )
        self.destroy()

    def CorrectSequence(self):
        comment_text = self.comment_text.get("1.0", tk.END).strip()
        if comment_text == "":
            return
        is_success, corrected = ds.CorrectEnglishSyntaxAndSpelling(comment_text)
        if is_success:
            self.comment_text.delete("1.0", tk.END)
            self.comment_text.insert(tk.END, corrected)
        else:
            messagebox.showerror("Error", f"Failed to correct the comment. {corrected}")

    def DeleteBag(self):
        if os.path.exists(self.bag_path):
            okcancel = messagebox.askokcancel(
                "Delete", f"Do you want delete {self.bag_path}."
            )
            if okcancel:
                os.remove(self.bag_path)
                self.destroy()

    def ReadResultJSON(self, json_file):
        if not os.path.exists(json_file):
            return None
        data = {}
        with open(json_file, "r") as file:
            data = json.load(file)
        if "result" in data:
            data = self.ConvertOldVersion(data)
            with open(json_file, "w") as file:
                json.dump(data, file, indent=4)
        bag_path = data.get("bag", "")
        results = []
        for key, value in data.items():
            if key.startswith("RUN"):
                results.append(value)
        return bag_path, results

    def UpdateResults(self, result_data):
        result = result_data.get("result", "")
        comment = ""
        if "comment" in result_data:
            comment = result_data.get("comment", "")
        elif "description" in result_data:
            comment = result_data.get("description", "")
        if result == "success" or result == "Success":
            self.result_var.set(value="success")
        elif result == "failure" or result == "Failure" or result == "":
            self.result_var.set(value="failure")
        if result == "success" or result == "Success":
            self.result_var.set(value="success")
        elif result == "failure" or result == "Failure" or result == "":
            self.result_var.set(value="failure")
        self.comment_text.delete("1.0", tk.END)
        self.comment_text.insert(tk.END, comment)

    def ConvertOldVersion(self, data):
        comment = ""
        if "comment" in data:
            comment = data.get("comment", "")
        elif "description" in data:
            comment = data.get("description", "")
        old_data = {"result": data.get("result", ""), "comment": comment}
        bag_path = data.get("bag", "")
        data = {"bag": bag_path, "RUN000": old_data}
        return data


class ResultWin(tk.Tk, ResultBase):
    def __init__(self, bag_path, patameters={}):
        tk.Tk.__init__(self)
        ResultBase.__init__(self, bag_path, patameters)
        self.title(f"Process Result: {self.base_name}")
        self.bind("<KeyPress>", lambda x: self.OnKeyPress(x))
        self.config(menu=self.menu_bar)

    def OnKeyPress(self, event):
        if event.keysym == "Return":
            self.ConfirmSelection()


class ResultWinTop(tk.Toplevel, ResultBase):
    def __init__(self, parent, bag_path, patameters={}):
        tk.Toplevel.__init__(self, parent)
        ResultBase.__init__(self, bag_path, patameters)
        self.title(f"Process Result: {self.base_name}")
        self.bind("<KeyPress>", lambda x: self.OnKeyPress(x))
        self.config(menu=self.menu_bar)

    def OnKeyPress(self, event):
        if event.keysym == "Return":
            self.ConfirmSelection()
